Learning about a new operating system usually includes knowing a bit about the components that compose it. You don't start learning about DOS by knowing that there are two hidden files (MSDOS.SYS and IO.SYS) and one visible file (COMMAND.COM) that make up its core, but you do learn about them later. It doesn't take very long for most people to figure out some of the things that take place under DOS as well. An in-depth knowledge of interrupts and vector tables isn't required, but a basic knowledge of what takes place is. Just about every user spends some time learning about ancillary system files as well. Everyone knows about the DOS configuration filesAUTOEXEC.BAT and CONFIG.SYSbecause you can't do much without them.
With this in mind, let's take a look at the Windows NT architecture and some of its components. I looked specifically at the workstation version of the product while writing this chapter but later verified that many of the pieces appear in the server product as well. I won't go into bits and bytes during this discussion. In fact, I barely scratch the surface of what Windows NT contains. Still, you'll gain an appreciation of what happens under the hood of this operating system. Having that knowledge can make it a lot easier to both configure and use Windows NT effectively.
I always like to take the grand tour of a new product before I get mired in detail. Getting the big picture first gives you a better idea of how all the small pieces fit in. That's the purpose of this sectionto give you the grand tour of Windows NT. I'll look at how all the subsystems that I describe in later chapters fit together to create a comprehensive operating system.
Before I begin a discussion of individual Windows architectural components, I'd like to direct your attention to the "rings" of protection that the 80386 (and above) processor provides. The Intel protection scheme has four security rings, but most operating systems use only two (or sometimes three) of them. The inner security ring is ring 0. This is where the operating system proper is. The outermost ring is 3, where the applications reside. Sometimes an operating system gives device drivers better access to some operating system features than an application gets by running them at ring 1 or 2. Windows doesn't make any concessions; device drivers run at ring 0 or 3, depending on their purpose.
Windows uses these protection rings to make certain that only operating system components can access the inner workings of Windows, so an application can't change settings that might cause the entire system to crash. Windows reserves the right to allocate memory from the global pool, for example; therefore, the capabilities needed to perform this task rest at ring 0. On the other hand, applications need to access memory assigned to them. That's why Windows assigns local memory a protection value of 3.
Think of each ring as a security perimeter. Before you can enter that perimeter, you have to know the secret password. Windows gives the password only to applications that it knows it can trust; everything else has to stay out. Whenever an application does try to circumvent security, the processor raises an exception. Think of an exception as a security alarm. The exception sends the Windows police (better known as an exception handler) after the offending application. After the arrest and trial, Windows calmly terminates the application. Of course, it notifies the user before performing this task, but the user usually doesn't have much of a choice in the matter.
Figure 6.1 (described in the next section) gives you a pretty good idea of exactly whom Windows trusts. Applications and device drivers running at ring 3 have very few capabilities outside their own resources. In fact, Windows even curtails these capabilities somewhat. Some of the activities that a DOS application could do, such as directly manipulating video memory, aren't allowed here. The reason is simple: Video memory is a shared resource. Whenever another application needs to share something, you can be certain that your application won't be able to access it directly.
Now, I move on to the various components that actually make up Windows. The following sections break the Windows components into main areas. Each of these general groups contains descriptions of the individual components and what tasks they perform. Remember that this is only a general discussion. Windows is much more complex than it might first appear. The deeper you get as a user, the more you'll notice the complexity of this operating system.
Several elements make up the Windows NT architecture, as shown in Figure 6.1. Each element takes care of one part of the Windows environment. The Windows Application Programming Interface (API) layer, for example, enables applications to communicate with Windows internals such as the file management system. You couldn't write a Windows application without the API layer. I describe each of these main components in detail in the following sections.
Figure 6.1. Windows contains several major elements, different services to the user, and other applications running under Windows.
The System Virtual Machine (VM) component of Windows NT contains four main elements: 32-bit Windows applications, the shell, POSIX application support, and OS/2 application support. Essentially, the System VM component provides most of the Windows NT user-specific functionality. Without it, you couldn't run any applications. Note that I don't include DOS applications here. Windows uses an entirely different set of capabilities to run DOS applications, even running them in a different processor mode.
You should notice one other thing about the OS/2 and POSIX support provided by Windows NT. There's a client side to this support in the System Virtual Machine area of the diagram and a server side in the Windows API layer part of the drawing. Windows NT uses a client/server approach to managing applications so that it can quickly adapt to applications designed for other operating systems by using this technique. This book really won't discuss the added support much, but you should at least be aware that it exists.
Warning: It might appear that you could run applications designed for different operating systems together under Windows NT and share their data. Although Windows NT will run more than one operating system's applications, it won't share data between them. A POSIX application and a Windows 32-bit application create file handles differently, for example. The POSIX file handle would be meaningless to the Windows NT application. The same idea holds true for any other type of data that an application might generate. In short, it's never a good idea to pass data from one application to another unless you use some documented method to do so.
Windows NT and Windows 95 show another difference in their 16-bit Windows application support. Unlike Windows 95, which still contains a lot of 16-bit code in some support areas, Windows NT uses all 32-bit code. This means that it can relegate 16-bit Windows applications to the MS-DOS Virtual Machine area. The bottom line from a user's perspective is that Windows NT provides a higher level of protection for 16-bit Windows applications. You won't see many application-induced crashes, and it's unlikely that even if you do, the system as a whole will crash. The down side of this protection is that Windows NT is also less tolerant of older 16-bit Windows applications that might have broken some of the rules for running properly with other applications.
Theoretically, the System VM provides support for the various Windows API layer components. Because these components provide a different sort of service, however, I chose to discuss them in a separate area (see "The Windows API Layer," later in this chapter). (Needless to say, the distinction between the client or System VM and server or Windows API layer parts of Windows NT architecture is a lot clearer than under Windows 95.) Even though applications use the API and users interact with applications, you really don't think about the API until it comes time to write an application. Therefore, I always think of the API as a programmer-specific service rather than something that the user needs to worry about. The following list describes the System VM components in detail:
Figure 6.2.Windows 95 sports a new interface that should make life a lot easier for the novice user.
Figure 6.3. Windows 3.0 and above offer one of the things that users need to use a computer efficiently: a graphical user interface (GUI).
Two Windows APIs are included with Windows NT. The first API is exactly like the old one supplied with Windows 3.1. It provides all the 16-bit services that the old Windows had to provide for applications. An older 16-bit application will use this API when it runs. The other API is the 32-bit Windows API used by Windows NT. The 32-bit API provides about the same feature set as the 16-bit API, but it's more robust.
You can physically see the two Windows APIs if you look in the right place. These two APIs exist side-by-side in separate files in your SYSTEM folder. All the common dialog boxes, for examplelike the ones you use to open files or search for text in your documentappear in two files: COMMDLG.DLL (16-bit) and COMDLG32.DLL (32-bit). The 32 in a filename often gives it away as a 32-bit program. Using common dialog boxes gives your applications the consistent look that you've come to expect. You'll find other pieces of the API in your SYSTEM folder as well. Microsoft groups various API calls together and places them in separate files to make it easier to update the operating system later. Using separate files also makes it easier to install upgrades to various operating system components and reduces the amount of hard disk space you lose to unwanted features.
Looking Ahead: Chapter 8, "Memory Management," takes a look at why Windows NT has to use two different files for 16-bit and 32-bit DLLs. It's the same chapter where I tell you all about the types of memory that Windows NT uses and how it affects you as a user. It's important to know about this area because it affects the way that your applications interact with Windows. Knowing this information will also help you understandat least a little betterwhy an application can't perform certain kinds of tasks even though it appears that they should be able to.
To support multiple operating systems, Windows NT also has to provide multiple API layers. Microsoft calls these API layers (or subsystems) servers. The main server under Windows NT is obviously the Windows API just discussedthe other servers talk to it. The client (in most cases, an application) for a particular operating system calls the API that it can talk to. The API will then translate system requests such as opening a file or printing a document into something that Windows NT can understand. An OS/2 client would call the OS/2 API, for example, which in turn calls the Windows API. If you look at the block diagram in Figure 6.1, you see three API layers: Windows subsystem, POSIX subsystem, and OS/2 subsystem. Even though this design is a lot different from the one used by Windows 3.x or Windows 95, the Windows NT 32-bit API looks just the same as the one in Windows 95 from a programmer's perspective (even though it does provide a wider range of calls). It's the actual operating system implementation that differs. For a user, the difference is completely transparent.
The base system component of Windows NT contains all the internal or low level operating-system-specific services. Some books call this the operating system kernel. This is the core of Windows NT, the part that has to be operating in order for Windows to perform its work. You, as a user, will never interact with the base system. Few programmers even interact with this "hidden" part of Windows. The following paragraphs describe each part of the base system in detail:
I've separated the section about the DOS Virtual Machine component of Windows from the other components' sections for several reasons. DOS applications have formed the basis for using the PC for a long time. In fact, for many years, nothing else was available. Most DOS applications were written at a time when the standard PC ran one application and one application only. That one application had total control of the entire machine.
Each DOS application that you start under Windows NT runs on what Intel terms a virtual machine. Essentially, the processor fools the application into thinking that it's the only application running on your machine at the moment. Each virtual machine has its own memory space and access to devices on the system. The amazing thing is that you can have many virtual machines running on your one physical machine at a time. I'll take a more detailed look at the DOS Virtual Machine later. Suffice it to say that Windows NT has to perform backflips to make this whole concept work properly, especially when you consider Windows-hostile applications such as games.
It might sound like Windows NT would lose control of the system when it runs a DOS application. The truth is that each one of these virtual machines is still under strict control of the processor. If the application makes a request that the processor can't fulfill, then the processor raises an exception. Windows NT pays close attention to these exceptions and doesn't allow a DOS application to continue running when it sees one. Windows NT also monitors display memory and every device on your machine. It terminates any applications that try to access a device improperly. This higher level of monitoring explains why Windows 95 will run applications such as game programs when Windows NT won't. Windows 95 allows an application to continue as long as it can recover from an error; Windows NT terminates the errant application.
Windows on Win32 (WOW) refers to the Windows NT way of handling 16-bit Windows applications. To begin the discussion, I look at a few facts about the Windows 3.x operating environment. Everyone knows that Windows 3.x provides the capability to run multiple applications using cooperative multitasking. There's an Achilles heel to this version of Windows, however. The basis for that operating environment is DOSa single-tasking operating system. In fact, early versions of Windows 3.x used DOS almost exclusively for disk-based and other system services. That reliance on DOS led to a lot of stability and speed problems that Microsoft cleared up over the years by adding protected-mode drivers to Windows. A good example of those efforts is Windows 95; it doesn't have to rely on DOS at all unless you use real-mode drivers.
You probably still have a lot of Windows 3.x 16-bit applications on your machine. All your older applicationsthe ones you own right noware 16-bit applications unless you bought them for use with Windows NT or Windows 95. To run these older applications, Windows NT starts a copy of DOS in a virtual machine and then runs a 16-bit version of Windows. Your 16-bit Windows applications run within this environment, just as they normally would. In essence, a 16-bit application that you use under Windows NT is running within a controlled DOS environment within the DOS Virtual Machine. This technique differs from Windows 95 where your 16-bit Windows applications run within the System Virtual Machine.
Just like Windows 95, Windows NT runs all your 16-bit Windows applications in one shared address space. Essentially, Windows NT groups all these 16-bit applications into one area and treats them as if they were one task. You really won't notice any performance hit as a result because this is the same environment that Windows 3.x provides for your application. Keeping this shared address space environment intact also makes it easier for Windows NT to recover from application errors. It simply monitors the MS-DOS Virtual Machine for any kind of error and then terminates the entire 16-bit Windows session if it detects one. Using this system allows Windows NT to mix 16-bit and 32-bit applications on one system without violating any of the reliability and security considerations that I've mentioned.
The first thing you need to understand is what an operating system kernel is all about. Think of the kernel as the very central core of the operating systemthe part that binds everything else together and provides a basic set of features. A programmer usually accesses the kernel using some special technique. DOS programmers know you're supposed to gain access to the operating system using an interrupt service routine, for example. These interrupts ask the operating system to perform a specific task. All the code for the interrupt routines appears in the system files. Under DOS, you'd find these system files in COMMAND.COM, MSDOS.SYS, and IO.SYS. (Some people would say that you don't actually need COMMAND.COM, and you don't, but you do need some type of system shell so I included the default here.) These three files load as part of the boot process and (except for COMMAND.COM) remain active the entire time you use DOS. This old method worked well in the DOS single-tasking environment, where the application was in control.
Under Windows, the user is in control, and the old system of interrupt service requests won't work properly. Every Windows application gains access to the operating system using an API. Essentially, an API call does the same thing as an interrupt: It asks the operating system to perform a task. The code for the API appears in the system files, just like it does for DOS. Of course, this is a very simplified view of the API. An API is written using protected-mode code, unlike DOS, which is written in real-mode code. In addition, API code is reentrant, but the DOS code isn't. A reentrant piece of code allows Windows 95 to process more than one call at a time. Under DOS, you couldn't reenter a piece of codeyou had to complete one call at a time (a reasonable limitation because only one application was supposed to be working at any given time under DOS). There are other differences as well, but the only people that really need to know about them are programmers. As discussed in the preceding section, Windows NT actually uses two Windows APIsone 16-bit and one 32-bit.
The API that most programmers concentrate on under Windows NT is the 32-bit API. Not only are 32-bit system calls a lot more logical from a programmer's point of view (Windows 3.x was a programmer's nightmare; Windows NT is merely an inconvenience), but they also provide more features as well. In addition, a 32-bit application enjoys the benefits that this environment provides. Of course, the benefit that you'll hear most programmers talk about is the flat memory address space. Every application running under Windowsuntil nowhas had to work with Intel's segmented address scheme. A 32-bit application doesn't need to worry about segmentation any more. Every call is a near call; every call is in a single segment.
No matter which API your Windows application uses, it'll address three basic operating system kernel components. The 16-bit versions of these files are GDI.EXE, USER.EXE, and KRNL386.EXE. The 32-bit versions of these files are GDI32.DLL, USER32.DLL, and KERNEL32.DLL. The following paragraphs describe these three components in detail.
Note: Windows NT supports other operating systems through the system of clients and servers that I discussed earlier in the chapter. In other words, the server translates the calls made by the application into a Windows API call. In essence, other operating systems' applications use the same kernel components that any Windows application does, even though they are designed for another operating system.
The kernel actually has a few more pieces, but it's better to think of them as you would the DOS loader. I didn't mention the DOS loader at the beginning of this discussion because no one ever uses it once the operating system is up and running. Likewise, Windows has to have some components that load it into memory and get it started. You won't hear too much about them because no one ever uses them once the operating system is started. The section "A Look at the Windows NT Boot Sequence" later in this chapter discusses the actual files.
What exactly is a miniport driver? This was the first question that came to my mind. Chapter 9 will touch on this particular topic when it describes the file system architecture. A miniport driver is a device-independent way of moving data. It doesn't matter what form that data takesit could be graphics, sound, or text. Windows NT uses the miniport driver concept for every subsystem on your machine. The benefit of using the miniport driver for your applications is improved speed. The application only needs to worry about the data it wants to output, not the format that the data takes.
Not only does miniport driver support mean a better and easier-to-use interface for the user, it also means a lot to software vendors as well. Under DOS, you have to write code for every little function. If you want to provide a File menu, you have to write all the code that the File menu requires. The same thing holds true for every other function a program might perform. Windows 3.x started a process in which the programmer didn't have to write so much code. Using the common dialog boxes is just one example. You no longer have to write a File menu because Microsoft provides one as part of the common dialog box DLL.
Windows NT takes this concept even further with the miniport driver support it provides. In developing communication programs, you used to worry about the differences in control sequences for each modem type. Using Windows NT Unimodem support (a miniport driver), the programmer opens each modem and writes to it like a file. The miniport driver takes care of details such as control codes.
This approach has other significant advantages. For one thing, you no longer need to worry as much about how well an application will handle the details. Because each vendor is writing to the same interface, any changes to that interface come from Microsoft. Using a common interface also means that every application provides the same level of support for the various devices on your system. If one application supports a device, they all support it to the same level.
Looking Ahead: I discuss the specifics of miniport driver implementation as I mention each subsystem. Chapter 9 covers the miniport driver concept from the file system point of view. See Chapter 10, "Graphics NT Style," for the same information on the video subsystem. Chapter 11, "Printing NT Style," covers printer support in more detail. Details on network miniport driver support appear in Chapter 21. In most cases, I shorten "miniport driver" to "driver" in the rest of the book because a miniport driver is simply a special form of driver.
Getting your machine up and running after you turn the power on is called the boot process. It includes everything from the time that the power on startup test (POST) routines begin until the time you can start to use the machine. Under DOS, this boot process was relatively straightforward. Windows NT requires something a bit more exotic because you expect it to do more.
I describe the boot process from a user's perspective in the following sections. This means you won't get a blow-by-blow "this bit does this and that byte does that" explanation. I just discuss the highlights of the boot process.
Tip: If you ever do want to see a blow-by-blow description of the entire boot process, look at BOOTLOG.TXT in the root directory of your boot drive. This file records every action that Windows NT performs during the boot process. It doesn't include a few of the initial actions, though, such as loading the Windows NT loader (NTLDR.BIN). At most, three or four actions take place before the log starts, though, so your chances of missing anything important are almost nonexistent.
Loading the initial system is fairly straightforward. The boot sector on the hard drive points to NTLDR.BINthe program that the BIOS calls as soon as the POST routine completes, just like it does with the DOS loader if you have DOS loaded. NTLDR.BIN calls the NTDETECT.COM program. This program displays the Windows NT splash screen.
NTDETECT.COM also begins a search for the computer's installed hardware. Once it gets a complete list, NTDETECT.COM displays the computer's hardware characteristics such as what kind of hard disk it uses and passes the information to other applications through the registry. This step is essential because Windows NT lacks any Plug and Play capability. The only time that it can really detect new hardware on your machine is during this step in the boot process.
Looking Ahead: The registry is discussed in full detail in Chapter 7, "Understanding the Windows NT Registry." You'll be amazed at what kind of information is stored theresuch as some information that used to appear in numerous .INI files on your drive.
Once NTDETECT.COM completes its task, it passes control back to NTLDR.BIN. The next phase in the operating system boot process is determining which operating system to load. BOOT.INI contains a list of operating systems installed on your machineusually DOS and Windows NT or OS/2 and Windows NT. It's at this point that Windows NT displays the screen that allows you to boot DOS or OS/2. If the countdown timer stops before you make a selection, Windows NT then begins to load the default operating system. (Chapter 4, "Setup Primer," describes how you can change the default operating system using the System applet in the Control Panel.)
Tip: You can always interrupt the countdown timer by pressing the up or down arrow. This gives you as much time as you need to choose an operating system; NTLDR.BIN will simply wait until you press the Enter key to begin the loading process.
The next step in the process is configuring Windows NT at a basic levelmuch like CONFIG.SYS does for a DOS machine. NTLDR.BIN looks in two places for this information. The registry contains all the hardware information it needs to configure the various devices on your system. In some cases, NTLDR.BIN needs to look in BOOT.INI to see which devices to use. The BOOT.INI file also tells Windows NT which services such as networking or a power monitor to start. (Chapter 4 showed that you could use the Services applet in the Control Panel to modify these settings.)
This part of the boot process worked mainly with the registry. Its whole function is to load some low-level executable files into memory to handle the rest of the loading process and configure Windows NT for use. It also allowed you to choose another operating system before Windows NT begins to load. Windows NT is still using NTLDR.BIN to get the job done, but now it needs to do something with the information that it's accumulated.
Windows NT still hasn't loaded any GUI elements into memory. The first thing to do is get the core Windows NT operating system loaded. To do this, NTLDR.BIN loads an application called VWIN32.386. This little program loads the three 32-bit DLLs that form the 32-bit API: USER32.DLL, GDI32.DLL, and KERNEL32.DLL. Once it completes this task, VWIN32.386 returns control to NTLDR.BIN, which in turn calls the 32-bit kernel.
Now that all the core operating system components are loaded, Windows NT loads and initializes all the 32-bit virtual device drivers (VxDs). It also loads all the servicesjust another form of VxD, but a form that you can communicate with.
What precisely is a VxD? It's a virtual device driver, the protected-mode version of the device drivers you used under DOS. It's also more than that, though, because a device can be a lot more than just a piece of hardware under Windows NT. To avoid getting into the bits and bytes of device management, let's just say that Windows uses virtual device drivers to manage all its low-level functions.
Once it completes this step, Windows initializes all those drivers. It starts with the system drivers firstall the drivers required to make the low-level functions in Windows work (such as the file system drivers). After initializing the system drivers, Windows NT initializes any services that you requested. The device drivers come next. Now that the 32-bit part of Windows NT is up and running, it creates one or more virtual DOS machines (VDMs).
Now that there is a place for 16-bit Windows to run, Windows NT starts a copy of it in memory. To do this, Windows NT loads the three 16-bit shell components: USER.EXE, GDI.EXE, and KRNL386.EXE. It also loads some additional drivers and a few other components such as fonts. The 16-bit driver load and initialization sequence is the same as for the 32-bit portion, so I won't go into it again here. Now, Windows NT has a completely functional 16-bit mode version of Windows available to run older applications. It doesn't have an interface yet, but every other component is present.
Sometime during the boot process, Windows NT asks the user to provide some input in the form of a name and password. It checks this against the contents of the appropriate .PWL file. If the password checks out, Windows NT completes the boot process.
Finally, Windows gets the Explorer interface up and running (it was loaded before but wasn't running). It displays all the required objects on the Desktop and initializes the Taskbar. This is the point where it also looks at your Startup folder to see which applications you want to start automatically. Then, you're set up and ready to compute.
I always find it interesting to see exactly what my computer is doing. Take a look through the BOOTLOG.TXT file on your boot drive to see which drivers Windows NT is loading and what order it loads them in. See if you can find all the drivers in your SYSTEM folder. You might be surprised to find that they don't all appear there. Which files (if any) does Windows NT place in other locations? Why do you think it places them there?
Check out your BOOT.INI file and then make a minor change using either the System or Services applet in CONFIG.SYS. How do these changes look? Knowing how Windows NT makes entries into this file could make it easier for you to recover if there's ever a problem in getting your system to boot. (I've never run into a problem that Windows NT automatic recovery couldn't fix, but you never know.) Make sure you return any settings to their previous condition before you exit Windows NT.
Spend some time in the SYSTEM folder trying to find various API elements. How do the 32-bit names differ from their 16-bit counterparts? Right-click on the API components and select Quick View from the context menu. Do you recognize any of the exported functions that the DLL provides?